package cn.com.yx.ms.service.impl;

import cn.com.yx.ms.application.web.ApiPager;
import cn.com.yx.ms.controller.RepairController;
import cn.com.yx.ms.domain.GlobalConfigModel;
import cn.com.yx.ms.domain.RepairLogModel;
import cn.com.yx.ms.domain.RepairLogSortModel;
import cn.com.yx.ms.domain.dbmodel.RepairLog;
import cn.com.yx.ms.domain.dbmodel.RepairLogSort;
import cn.com.yx.ms.persistence.RepairLogMapper;
import cn.com.yx.ms.persistence.RepairLogSortMapper;
import cn.com.yx.ms.service.IRepairService;
import cn.com.yx.ms.service.ISysService;
import cn.yx.framework.configuration.ApiCode;
import cn.yx.framework.configuration.AppConstant;
import cn.yx.framework.configuration.AutoReportConfig;
import cn.yx.framework.configuration.BaseConstant;
import cn.yx.framework.security.MD5Util;
import cn.yx.framework.util.DateUtil;
import cn.yx.framework.view.ApiResult;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;

/**
 * 报修相关接口实现
 */
@Service
@Transactional
public class RepairServiceImpl implements IRepairService {

    @Resource
    private RepairLogSortMapper repairLogSortMapper;
    @Resource
    private RepairLogMapper repairLogMapper;
    @Resource
    AutoReportConfig autoReportConfig;
    @Resource
    ISysService iSysService;

    private static final String LOGSORTID = "7274cef5-56b7-4b03-bed3-09abaec99532";

    private static final Logger logger = LoggerFactory.getLogger(RepairServiceImpl.class);

    /**
     * 报修类型一览获取
     *
     * @return
     */
    @Override
    public ApiResult findRepairType() {
        ApiResult result = null;

        List<RepairLogSort> list = repairLogSortMapper.findRepairType();

        if (null == list || list.size() == 0) {
            result = new ApiResult(AppConstant.MSG_FAILURE, false, "报修类型获取失败");
        } else {
            result = new ApiResult().success(AppConstant.MSG_SUCCESS, "", list);
        }
        return result;
    }

    /**
     * 报修操作(手动报修)
     *
     * @param repairLog
     * @return
     */
    @Override
    public ApiResult report(RepairLog repairLog) {
        ApiResult result = new ApiResult();

        // 配置文件取值
        repairLog.setKey(autoReportConfig.autoReportServer().getKey());
        repairLog.setRequest_ownerorgid(autoReportConfig.autoReportServer().getOwnerorgid());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        repairLog.setSign(autoReportConfig.autoReportServer().getSecret()
                + "deviceId" + repairLog.getRequest_deviceid()
                + "ownerOrgId" + autoReportConfig.autoReportServer().getOwnerorgid()
                + "repairEndTime" + sdf.format(repairLog.getRequest_repairendtime()));

        InputStream is;
        BufferedReader br;
        StringBuilder sBuilder = null;

        // 提交到万维宝自动报修
        String reportUrl = autoReportConfig.autoReportServer().getUrl();
        String isProxy = autoReportConfig.autoReportServer().getIsproxy();

        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(reportUrl);

            // 设置代理
            if ("true".equals(isProxy)) {
                HttpHost proxy = new HttpHost(autoReportConfig.autoReportServer().getProxyurl(), Integer.parseInt(autoReportConfig.autoReportServer().getProxyport()), "http");
                RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
                httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
//                httpPost.setConfig(config);
            }

            // 传递多个参数
            List<NameValuePair> parameters = new ArrayList<>();
            parameters.add(new BasicNameValuePair("key", repairLog.getKey()));
            parameters.add(new BasicNameValuePair("sign", MD5Util.md5Str(repairLog.getSign())));
            parameters.add(new BasicNameValuePair("deviceId", repairLog.getRequest_deviceid()));
            parameters.add(new BasicNameValuePair("ownerOrgId", repairLog.getRequest_ownerorgid()));
            parameters.add(new BasicNameValuePair("repairEndTime", sdf.format(repairLog.getRequest_repairendtime())));
            parameters.add(new BasicNameValuePair("reportReason", "网络故障"));
            httpPost.setEntity(new UrlEncodedFormEntity(parameters, "utf-8"));
            HttpResponse httpResponse = httpClient.execute(httpPost);
            // 连接成功
            if (200 == httpResponse.getStatusLine().getStatusCode()) {
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
                br = new BufferedReader(new InputStreamReader(is));
                String tempStr;
                sBuilder = new StringBuilder();
                while ((tempStr = br.readLine()) != null) {
                    sBuilder.append(tempStr);
                }
                br.close();
                is.close();

                // UUid
                repairLog.setGuid(UUID.randomUUID().toString());

                // 报修类型(手工)
                repairLog.setReporttype("0");

                // 报修时间
                repairLog.setRequest_time(new Date());

                // 维修开始时间
                repairLog.setRequest_repairestarttime(new Date());

                int rt = repairLogMapper.insertSelective(repairLog);

                if (rt > 0) {
                    result = new ApiResult().success(AppConstant.MSG_SUCCESS, "", null);
                    logger.debug("上报成功，上报时间:" + sdf.format(new Date()));
                } else {
                    result = new ApiResult(AppConstant.MSG_FAILURE, false, "报修失败");
                    logger.debug("上报失败，上报时间:" + sdf.format(new Date()));
                }
            }
        } catch (Exception e) {
            result = new ApiResult(AppConstant.MSG_FAILURE, false, "报修失败");
            logger.debug("上报失败，上报时间:" + sdf.format(new Date()) + ",失败说明:" + e.getMessage());
        }

        return result;
    }

    /**
     * 简单报修接口
     *
     * @param equipmentNo
     * @param content
     * @return
     */
    @Override
    public ApiCode alertReport(String equipmentNo,String alertType,String content) throws Exception {
        ApiCode apiCode = ApiCode.APP_100200;

        // 获取全局配置对象信息
        GlobalConfigModel globalConfigModel = iSysService.findGlobalConfig();

        // 开始异步请求报修接口
        RequestConfig requestConfig = null;
        CloseableHttpAsyncClient httpclient = null;
        try {

            final CountDownLatch latch = new CountDownLatch(1);
            HttpPost request = new HttpPost("http://" + globalConfigModel.getWwb_request_serverip() + "/" + globalConfigModel.getWwb_request_proxy());

            // 设置代理
            if (StringUtils.isNoneBlank(globalConfigModel.getWwb_request_virtualurl())) {
                String proxyIp = "";
                int proxyPort = 80;

                // todo 代理地址需要重新配置及测试
                HttpHost proxy = new HttpHost(proxyIp, proxyPort, "http");
                requestConfig = RequestConfig.custom()
                        .setSocketTimeout(3000)
                        .setConnectTimeout(3000)
                        .setProxy(proxy).build();
                httpclient = HttpAsyncClients.custom()
                        .setDefaultRequestConfig(requestConfig)
                        .setProxy(proxy)
                        .build();

//                httpPost.setConfig(config);
            } else {
                requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000).build();
                httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
            }

            httpclient.start();
            List<BasicNameValuePair> urlParams = new ArrayList<>();
            String endTime = DateUtil.date2String(DateUtil.addDays(new Date(), 30), "yyyy-MM-dd HH:mm:ss");
            String sign = globalConfigModel.getWww_request_secret()
                    + "deviceId" + equipmentNo
                    + "ownerOrgId" + globalConfigModel.getSysid()
                    + "repairEndTime" + endTime;
            urlParams.add(new BasicNameValuePair("key", globalConfigModel.getWwb_request_appid()));
            urlParams.add(new BasicNameValuePair("sign", MD5Util.getMD5String(sign)));
            urlParams.add(new BasicNameValuePair("deviceId", equipmentNo));
            urlParams.add(new BasicNameValuePair("ownerOrgId", globalConfigModel.getSysid()));
            urlParams.add(new BasicNameValuePair("repairEndTime", endTime));
            urlParams.add(new BasicNameValuePair("reportReason", content));
            urlParams.add(new BasicNameValuePair("faultType",alertType));


            String getUrl = EntityUtils
                    .toString(new UrlEncodedFormEntity(urlParams));
            request.setURI(new URI(request.getURI().toString()
                    + "?" + getUrl));
            Future<HttpResponse> future = httpclient.execute(request, new FutureCallback<HttpResponse>() {
                //无论完成还是失败都调用countDown()
                @Override
                public void completed(final HttpResponse response) {
                    latch.countDown();
                    System.out.println(request.getRequestLine() + "->"
                            + response.getStatusLine());

                    InputStream is;
                    BufferedReader br;
                    StringBuilder sBuilder = null;

                    try {
                        HttpEntity httpEntity = response.getEntity();
                        is = httpEntity.getContent();
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                        String tempStr;
                        sBuilder = new StringBuilder();
                        while ((tempStr = br.readLine()) != null) {
                            sBuilder.append(tempStr);
                        }
                        br.close();
                        is.close();
                        System.out.println(sBuilder);
                    } catch (Exception ex) {

                    }
                }

                @Override
                public void failed(final Exception ex) {
                    latch.countDown();
                    System.out.println(request.getRequestLine() + "->" + ex);
                }

                @Override
                public void cancelled() {
                    latch.countDown();
                    System.out.println(request.getRequestLine()
                            + " cancelled.");
                }
            });

            latch.await();
            System.out.println("Shutting down");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpclient.close();
            System.out.println("close");
        }

        return apiCode;
    }

    /**
     * 获取报修日志一览
     *
     * @return
     */
    @Override
    public ApiResult findAllRepairLog(RepairLogModel repairLog) {
        ApiResult result = null;

        // 翻页对象构建
        PageHelper.startPage(repairLog.getPage_pi(), repairLog.getPage_ps(), true);
        Page<RepairLog> page = (Page<RepairLog>) repairLogMapper.findAllRepairLog(repairLog);

        ApiPager<RepairLog> apiPager = new ApiPager<>(repairLog.getPage_ps(),
                repairLog.getPage_pi(),
                page.getTotal(),
                page.getResult());

        return new ApiResult<>(AppConstant.MSG_SUCCESS, true, "", apiPager);
    }

    /**
     * 根据guid删除报修日志
     *
     * @param guid 日志id
     * @return
     */
    @Override
    public ApiResult delRepairLog(String guid) {
        ApiResult result = null;

        int rt = repairLogMapper.delRepairLog(guid);

        if (rt > 0) {
            result = new ApiResult().success(AppConstant.MSG_SUCCESS, "", null);
        } else {
            result = new ApiResult(AppConstant.MSG_FAILURE, false, "删除日志失败");
        }

        return result;
    }

    /**
     * 删除报修日志信息(多选)
     *
     * @param model 日志id
     * @return
     */
    @Override
    public ApiResult delAllRepairLog(RepairLogModel model) {
        ApiResult result = null;
        int rt = repairLogMapper.delAllRepairLog(model);

        if (rt > 0) {
            result = new ApiResult().success(AppConstant.MSG_SUCCESS, "", null);
        } else {
            result = new ApiResult(AppConstant.MSG_FAILURE, false, "删除日志失败");
        }

        return result;
    }

    /**
     * 获取报修日志分类一览
     *
     * @param model
     * @return
     */
    @Override
    public ApiResult findAllRepairLogSort(RepairLogSortModel model) {
        ApiResult result = null;

        // 翻页对象构建
        PageHelper.startPage(model.getPage_pi(), model.getPage_ps(), true);
        Page<RepairLogSortModel> page = (Page<RepairLogSortModel>) repairLogSortMapper.findAllRepairLogSort(model);

        ApiPager<RepairLogSortModel> apiPager = new ApiPager<>(model.getPage_ps(),
                model.getPage_pi(),
                page.getTotal(),
                page.getResult());

        return new ApiResult<>(AppConstant.MSG_SUCCESS, true, "", apiPager);
    }

    /**
     * 添加编辑报修日志分类
     *
     * @param repairLogSort
     * @return
     */
    @Override
    public ApiResult addRepairType(RepairLogSort repairLogSort) {
        ApiResult result = null;

        int rt = 0;

        String typeName = "";

        // 是否删除
        repairLogSort.setIsdeleted("0");

        if (StringUtils.isEmpty(repairLogSort.getGuid())) {
            // UUid
            repairLogSort.setGuid(UUID.randomUUID().toString());

            rt = repairLogSortMapper.insertSelective(repairLogSort);

            typeName = "添加";
        } else {
            rt = repairLogSortMapper.updateByPrimaryKeySelective(repairLogSort);
            typeName = "修改";
        }

        if (rt > 0) {
            result = new ApiResult().success(AppConstant.MSG_SUCCESS, "", typeName + "分类成功");
        } else {
            result = new ApiResult(AppConstant.MSG_FAILURE, false, typeName + "分类失败");
        }

        return result;
    }

    /**
     * 删除报修日志类型(单选)
     *
     * @param guid 日志类型id
     * @return
     */
    @Override
    public ApiResult delRepairLogSortType(String guid) {
        ApiResult result = null;

        int rt = repairLogSortMapper.delRepairLogSortType(guid);

        if (rt > 0) {
            result = new ApiResult().success(AppConstant.MSG_SUCCESS, "", null);
        } else {
            result = new ApiResult(AppConstant.MSG_FAILURE, false, "删除日志类型失败");
        }

        return result;
    }

    /**
     * 删除报修日志类型信息(多选)
     *
     * @param model 日志类型id
     * @return
     */
    @Override
    public ApiResult delAllRepairLogSort(RepairLogModel model) {
        ApiResult result = null;
        int rt = repairLogSortMapper.delAllRepairLogSort(model);

        if (rt > 0) {
            result = new ApiResult().success(AppConstant.MSG_SUCCESS, "", null);
        } else {
            result = new ApiResult(AppConstant.MSG_FAILURE, false, "删除日志类型失败");
        }

        return result;
    }

    /**
     * 自动报修符合条件设备一览获取
     *
     * @return
     */
    @Override
    public ApiResult autoRepairCheck() {
        // 获取时间段内有问题设备一览
        List<RepairLogModel> list = repairLogMapper.autoRepairCheck();

        if (null == list || list.size() == 0) {
            logger.debug("没有找到符合条件的设备!");
            return new ApiResult().success(AppConstant.MSG_SUCCESS, "", null);
        }

        for (int i = 0; i < list.size(); i++) {
            RepairLogModel model = list.get(i);

            RepairLog repairLog = new RepairLog();

            repairLog.setKey(autoReportConfig.autoReportServer().getKey());
            repairLog.setRequest_deviceid(model.getDevsn());
            repairLog.setRequest_ownerorgid(autoReportConfig.autoReportServer().getOwnerorgid());
            repairLog.setRequest_reportreson("网络故障");


            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Calendar calendar = Calendar.getInstance();

            // 5天后时间
            calendar.add(Calendar.DATE, 5);
            repairLog.setRequest_repairendtime(calendar.getTime());

            repairLog.setSign(autoReportConfig.autoReportServer().getSecret() + "deviceId" + repairLog.getRequest_deviceid()
                    + "ownerOrgId" + autoReportConfig.autoReportServer().getOwnerorgid() + "repairEndTime" + sdf.format(repairLog.getRequest_repairendtime()));

            repairLog.setCreater("0");
            repairLog.setLogsortid(LOGSORTID);

            // 报修操作
            ApiResult result = this.report(repairLog);
            if (!result.isSucc()) {
                return new ApiResult().failure(AppConstant.MSG_FAILURE, "上报失败", null);
            }
        }
        return new ApiResult().success(AppConstant.MSG_SUCCESS, "", null);
    }
}
